package com.hgk.common.common.ui.view;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.Bitmap;
import android.net.Uri;
import android.net.http.SslError;
import android.os.Build;
import android.os.Message;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.View;
import android.webkit.DownloadListener;
import android.webkit.HttpAuthHandler;
import android.webkit.JsPromptResult;
import android.webkit.JsResult;
import android.webkit.SslErrorHandler;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;

import com.common.dongqiuhui.apps.comm.tools.BallLog;
import com.common.dongqiuhui.apps.comm.tools.BallUtil;
import com.common.dongqiuhui.apps.comm.tools.UIC;
import com.hgk.common.common.ui.activity.BallWebviewActivity;

import org.json.JSONArray;
import org.json.JSONObject;

import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class BallWebView extends WebView {
	private static final String TAG = BallWebView.class.getSimpleName();

	private Activity mContext;
    private ArrayList<String> loadHistoryUrls = new ArrayList<String>();
    /**
	 * 登录回调的请求码【网页调用本地登录页面】
	 */
	public final int WEB_VIEW_CALL_NATIVE_LOGIN_REQUEST_CODE = 0xffff;
	/**
	 * 关闭打印选择，介绍也广播Action
	 */
	public final static String CLOSE_ACTION = "print_close_page";
	private ArrayList<String> mJsList = new ArrayList<String>();
	private boolean mIsLoadFinished = false;

	private ArrayList<String> mCacheUrls = new ArrayList<String>();
	private boolean mCanGoBack = true;
	private boolean mIsShowTitle = true;

	// 统计事件
	private String mStatisticsEvent = null;

	private static final String VAR_ARG_PREFIX = "arg";
	private static final String KEY_INTERFACE_NAME = "obj";
	private static final String KEY_FUNCTION_NAME = "func";
	private static final String KEY_ARG_ARRAY = "args";
	private static final String[] mFilterMethods = { "getClass", "hashCode",
			"notify", "notifyAll", "equals", "toString", "wait", };
	private HashMap<String, Object> mJsInterfaceMap = new HashMap<String, Object>();
	private String mJsStringCache = null;
    private ProgressBar progressbar;

	public BallWebView(Context context) {
		super(context);
		init(context);
	}

	public BallWebView(Context context, AttributeSet attrs) {
		super(context, attrs);
		if (!isInEditMode()) {
			init(context);
		}
	}

	public BallWebView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init(context);
	}

	@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
	@SuppressWarnings("deprecation")
	@SuppressLint({ "SetJavaScriptEnabled", "NewApi" })
	private void init(Context context) {
		mContext = (Activity) context;
		initJsList();
		WebSettings webSettings = getSettings();
		webSettings.setCacheMode(WebSettings.LOAD_DEFAULT);
		webSettings.setSavePassword(false);
		webSettings.setSaveFormData(false);
		webSettings.setJavaScriptEnabled(true); // 支持JS操作
		webSettings.setSupportZoom(true);
        webSettings.setDomStorageEnabled(true);
		webSettings.setBuiltInZoomControls(true);
		webSettings.setSupportMultipleWindows(true); // 支持可以缩放
		webSettings.setUseWideViewPort(true); // 支持任何缩放比例
		webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
		webSettings.setLoadsImagesAutomatically(true); // 设置自动加载图片
		webSettings.setLoadWithOverviewMode(true); // 加载的页面的模式
		webSettings.setDefaultTextEncodingName("UTF-8");
		setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
		setWebViewClient(new MyWebViewClient());
		setDownloadListener(new MyWebViewDownLoadListener());
		setWebChromeClient(new MyWebChromeClient());
		// 删除掉Android默认注册的JS接口
		removeSearchBoxImpl();
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
			try {
				webSettings.setMediaPlaybackRequiresUserGesture(false);
			} catch (Throwable e) {
				BallLog.e(TAG, "init e[" + e + "]");
			}
		}

		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
			try {
				WebView.setWebContentsDebuggingEnabled(true);
			} catch (Throwable e) {
				BallLog.e(TAG, "init e[" + e + "]");
			}
		}
		//addJavascriptInterface(new JavaScriptInterface(), "android");
	}

	@Override
	public void addJavascriptInterface(Object obj, String interfaceName) {
		if (TextUtils.isEmpty(interfaceName)) {
			return;
		}

		// 如果在4.2以上，直接调用基类的方法来注册
		if (hasJellyBeanMR1()) {
			super.addJavascriptInterface(obj, interfaceName);
		} else {
			mJsInterfaceMap.put(interfaceName, obj);
		}
	}

	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	@Override
	public void removeJavascriptInterface(String interfaceName) {
		if (hasJellyBeanMR1()) {
			super.removeJavascriptInterface(interfaceName);
		} else {
			mJsInterfaceMap.remove(interfaceName);
			mJsStringCache = null;
			injectJavascriptInterfaces();
		}
	}

	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	private boolean removeSearchBoxImpl() {
		if (hasHoneycomb() && !hasJellyBeanMR1()) {
			super.removeJavascriptInterface("searchBoxJavaBridge_");
			return true;
		}

		return false;
	}

	private void injectJavascriptInterfaces() {
		if (!TextUtils.isEmpty(mJsStringCache)) {
			loadJavascriptInterfaces();
			return;
		}

		String jsString = genJavascriptInterfacesString();
		mJsStringCache = jsString;
		loadJavascriptInterfaces();
	}

	private void injectJavascriptInterfaces(WebView webView) {
		if (webView instanceof BallWebView) {
			injectJavascriptInterfaces();
		}
	}

	private void loadJavascriptInterfaces() {
		if (!TextUtils.isEmpty(mJsStringCache)) {
			super.loadUrl(mJsStringCache);
		}
	}

	private String genJavascriptInterfacesString() {
		if (mJsInterfaceMap.size() == 0) {
			mJsStringCache = null;
			return null;
		}

		/*
		 * 要注入的JS的格式，其中XXX为注入的对象的方法名，例如注入的对象中有一个方法A，那么这个XXX就是A
		 * 如果这个对象中有多个方法，则会注册多个window.XXX_js_interface_name块，我们是用反射的方法遍历
		 * 注入对象中的所有带有@JavaScripterInterface标注的方法
		 * 
		 * javascript:(function JsAddJavascriptInterface_(){
		 * if(typeof(window.XXX_js_interface_name)!='undefined'){
		 * console.log('window.XXX_js_interface_name is exist!!'); }else{
		 * window.XXX_js_interface_name={ XXX:function(arg0,arg1){ return
		 * prompt(
		 * 'BabytreeApp:'+JSON.stringify({obj:'XXX_js_interface_name',func:'XXX_',args:[arg0,arg1]}));
		 * }, }; } })()
		 */

		Iterator<Entry<String, Object>> iterator = mJsInterfaceMap.entrySet()
				.iterator();
		// Head
		StringBuilder script = new StringBuilder();
		script.append("javascript:(function JsAddJavascriptInterface_(){");

		// Add methods
		try {
			while (iterator.hasNext()) {
				Entry<String, Object> entry = iterator.next();
				String interfaceName = entry.getKey();
				Object obj = entry.getValue();

				createJsMethod(interfaceName, obj, script);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		// End
		script.append("})()");

		return script.toString();
	}

	private void createJsMethod(String interfaceName, Object obj,
			StringBuilder script) {
		if (TextUtils.isEmpty(interfaceName) || (null == obj)
				|| (null == script)) {
			return;
		}

		Class<? extends Object> objClass = obj.getClass();

		script.append("if(typeof(window.").append(interfaceName)
				.append(")!='undefined'){");
		script.append("}else {");
		script.append("    window.").append(interfaceName).append("={");

		// Add methods
		Method[] methods = objClass.getMethods();
		for (Method method : methods) {
			String methodName = method.getName();
			// 过滤掉Object类的方法，包括getClass()方法，因为在Js中就是通过getClass()方法来得到Runtime实例
			if (filterMethods(methodName)) {
				continue;
			}

			script.append("        ").append(methodName).append(":function(");
			// 添加方法的参数
			int argCount = method.getParameterTypes().length;
			if (argCount > 0) {
				int maxCount = argCount - 1;
				for (int i = 0; i < maxCount; ++i) {
					script.append(VAR_ARG_PREFIX).append(i).append(",");
				}
				script.append(VAR_ARG_PREFIX).append(argCount - 1);
			}

			script.append(") {");

			// Add implementation


			// Begin JSON
			script.append("JSON.stringify({");
			script.append(KEY_INTERFACE_NAME).append(":'")
					.append(interfaceName).append("',");
			script.append(KEY_FUNCTION_NAME).append(":'").append(methodName)
					.append("',");
			script.append(KEY_ARG_ARRAY).append(":[");
			// 添加参数到JSON串中
			if (argCount > 0) {
				int max = argCount - 1;
				for (int i = 0; i < max; i++) {
					script.append(VAR_ARG_PREFIX).append(i).append(",");
				}
				script.append(VAR_ARG_PREFIX).append(max);
			}

			// End JSON
			script.append("]})");
			// End prompt
			script.append(");");
			// End function
			script.append("        }, ");
		}

		// End of obj
		script.append("    };");
		// End of if or else
		script.append("}");
	}

	private boolean handleJsInterface(WebView view, String url, String message,
			String defaultValue, JsPromptResult result) {
		String prefix="";
		if (!message.startsWith(prefix)) {
			return false;
		}

		String jsonStr = message.substring(prefix.length());
		try {
			JSONObject jsonObj = new JSONObject(jsonStr);
			String interfaceName = jsonObj.getString(KEY_INTERFACE_NAME);
			String methodName = jsonObj.getString(KEY_FUNCTION_NAME);
			JSONArray argsArray = jsonObj.getJSONArray(KEY_ARG_ARRAY);
			Object[] args = null;
			if (null != argsArray) {
				int count = argsArray.length();
				if (count > 0) {
					args = new Object[count];

					for (int i = 0; i < count; ++i) {
						args[i] = argsArray.get(i);
					}
				}
			}

			if (invokeJSInterfaceMethod(result, interfaceName, methodName, args)) {
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		result.cancel();
		return false;
	}

	private boolean invokeJSInterfaceMethod(JsPromptResult result,
			String interfaceName, String methodName, Object[] args) {

		boolean succeed = false;
		final Object obj = mJsInterfaceMap.get(interfaceName);
		if (null == obj) {
			result.cancel();
			return false;
		}

		Class<?>[] parameterTypes = null;
		int count = 0;
		if (args != null) {
			count = args.length;
		}

		if (count > 0) {
			parameterTypes = new Class[count];
			for (int i = 0; i < count; ++i) {
				parameterTypes[i] = getClassFromJsonObject(args[i]);
			}
		}

		try {
			Method method = obj.getClass()
					.getMethod(methodName, parameterTypes);
			Object returnObj = method.invoke(obj, args); // 执行接口调用
			boolean isVoid = returnObj == null
					|| returnObj.getClass() == void.class;
			String returnValue = isVoid ? "" : returnObj.toString();
			result.confirm(returnValue); // 通过prompt返回调用结果
			succeed = true;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (Exception e) {
			e.printStackTrace();
		}

		result.cancel();
		return succeed;
	}

	private Class<?> getClassFromJsonObject(Object obj) {
		Class<?> cls = obj.getClass();

		// js对象只支持int boolean string三种类型
		/*
		 * if (cls == Integer.class) { cls = Integer.TYPE; } else
		 */
		if (cls == Boolean.class) {
			cls = Boolean.TYPE;
		} else {
			cls = String.class;
		}

		return cls;
	}

	private boolean filterMethods(String methodName) {
		for (String method : mFilterMethods) {
			if (method.equals(methodName)) {
				return true;
			}
		}

		return false;
	}

	private boolean hasHoneycomb() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB;
	}

	private boolean hasJellyBeanMR1() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
	}

	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
	@Override
	public void destroy() {
		// 解决联想K900 食谱放大缩小退出挂掉, Receiver not registered:
		// android.widget.ZoomButtonsController
		setVisibility(View.GONE);
		// 红米 NOTE 成长宝典视频播放时退出webview, 视频不停问题
		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
			onPause();
		}
		super.destroy();
	}

	public void setSupportZoom(boolean support) {
		WebSettings webSettings = getSettings();
		webSettings.setSupportZoom(support);
	}







	/**
	 * 设置统计事件
	 * 
	 * @param event
	 */
	public void setStatisticsEvent(String event) {
		mStatisticsEvent = event;
	}

	/**
	 * 获取统计事件
	 * 
	 * @return
	 */
	public String getStatisticsEvent() {
		return mStatisticsEvent;
	}

	public String getFinalUrl(String urlString) {
		String result = urlString;
		if (!TextUtils.isEmpty(urlString)
				&& BallUtil.startsWithIgnoreCase(result, "http")) {
			try {
				URL url = new URL(urlString);
				String queryString = url.getQuery();
				Uri.Builder builder = Uri.parse(urlString).buildUpon();
				HashMap<String, String> params = getBabytreeParams(urlString);
				Iterator<Entry<String, String>> it = params.entrySet()
						.iterator();
				while (it.hasNext()) {
					Entry<String, String> entry = it.next();
					// 优化, 重复插入的公共参数过滤
					if (null == queryString
							|| !BallUtil.containsWithIgnoreCase(
									queryString, entry.getKey())) {
						builder.appendQueryParameter(entry.getKey(),
								entry.getValue());
					}
				}
				result = builder.build().toString();
				funSetCookie(UIC.decodeFinal(result), mContext);
			} catch (Exception e) {
				BallLog.e(TAG, "getFinalUrl e[" + e + "]");
			}
		}
		// BabytreeLog.i(TAG, "getFinalUrl urlString[" + urlString + "] result["
		// + result + "]");
		return result;
	}



	@Override
	public void loadUrl(String url) {
		commloadUrl(getFinalUrl(BallUtil.getSplitUrl(url)));
	}

	@TargetApi(Build.VERSION_CODES.FROYO)
	@Override
	public void loadUrl(String url, Map<String, String> additionalHttpHeaders) {
		commloadUrl(getFinalUrl(url));
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK && canGoBack()) {
			goBack();
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	private void funSetCookie(String url, Context context) {

		String host = null;

		if (url != null) {
			try {
				host = getHost(url);
			} catch (Exception ex) {
				ex.printStackTrace();
			}

			//BabytreeUtil.setCookies(context, url, cookies);
		}
	}

	private String getHost(String urlString) throws Exception {
		URL url = new URL(urlString);
		return url.getHost();
	}

	/**
	 * 是否在http head或url中添加参数
	 * 
	 * @param url
	 * @return
	 */
	private boolean isAddParams(String url) {
		boolean result = false;
		return result;
	}

	/**
	 * 获取预制参数
	 * 
	 * @return
	 */
	private HashMap<String, String> getBabytreeParams(String url) {
		HashMap<String, String> result = new HashMap<String, String>();
		return result;
	}

	/**
	 * 客户端在header头里面增加以下字段：<br>
	 * babytree_app_id 如lama<br>
	 * babytree_client_type 如android、ios <br>
	 * babytree_app_version 如1.1 babytree_mac<br>
	 * <p/>
	 * 安卓2.1及以下版本无法支持<br>
	 */
	@TargetApi(Build.VERSION_CODES.FROYO)
	private void commloadUrl(String innerUrl) {
		if (!TextUtils.isEmpty(innerUrl)) {
			if (Build.VERSION.SDK_INT >= 8) {
				super.loadUrl(innerUrl, getBabytreeParams(innerUrl));
			} else {
				super.loadUrl(innerUrl);
			}
		}
	}

	public void addJsUrl(ArrayList<String> list) {
		for (int i = 0; i < list.size(); i++) {
			String url = list.get(i);
			if (!TextUtils.isEmpty(url)) {
				super.loadUrl(url);

			}
		}
	}

	/**
	 * 执行javascript，如果没页面没加载完成，添加到js list中页面加载完成后统一执行
	 * 
	 * @param javascript
	 */
	public void runJavascript(String javascript) {
		if (mIsLoadFinished) {
			super.loadUrl(javascript);
		} else {
			mJsList.add(javascript);
		}
	}

	/**
	 * 获取jsList 传给Fragment
	 */
	private ArrayList<String> getJsList() {
		return mJsList;
	}

	/**
	 * 获取jsList 传给Fragment
	 */
	private void initJsList() {
		//mJsList.add(CUSTOM_CREATE_TOPIC_JS);

	}






	class MyWebViewDownLoadListener implements DownloadListener {
		@Override
		public void onDownloadStart(String url, String userAgent,
				String contentDisposition, String mimetype, long contentLength) {
			// android.content.ActivityNotFoundException
			try {
				Uri uri = Uri.parse(url);
				Intent intent = new Intent(Intent.ACTION_VIEW, uri);
				mContext.startActivity(intent);
			} catch (Throwable e) {
				e.printStackTrace();
			}
		}
	}

	class MyWebChromeClient extends WebChromeClient {
		@Override
		public final void onProgressChanged(WebView view, int newProgress) {
			injectJavascriptInterfaces(view);
			//loadUrl(userInfoJs);
            if (newProgress == 100) {
                ((BallWebviewActivity)mContext).mProgressBar.setVisibility(View.GONE);
            } else {
                if (View.GONE == ((BallWebviewActivity)mContext).mProgressBar.getVisibility()) {
                    ((BallWebviewActivity)mContext).mProgressBar.setVisibility(View.VISIBLE);
                }
                ((BallWebviewActivity)mContext).mProgressBar.setProgress(newProgress);
            }
			super.onProgressChanged(view, newProgress);
		}

		@Override
		public final boolean onJsPrompt(WebView view, String url,
				String message, String defaultValue, JsPromptResult result) {
			if (view instanceof BallWebView) {
				if (handleJsInterface(view, url, message, defaultValue, result)) {
					return true;
				}
			}

			return true;
		}

		@Override
		public final void onReceivedTitle(WebView view, String title) {
			injectJavascriptInterfaces(view);
		}

		@Override
		public boolean onJsAlert(WebView view, String url, String message,
				final JsResult result) {
			try {
				new AlertDialog.Builder(mContext)
						.setTitle("提示")
						.setMessage(message)
						.setPositiveButton(android.R.string.ok,
								new AlertDialog.OnClickListener() {
									public void onClick(DialogInterface dialog,
											int which) {
										result.confirm();
									}
								}).setCancelable(true).create().show();
			} catch (Exception e) {
				BallLog.e(TAG, "onJsAlert e[" + e + "]");
			}
			return true;
		}

		@Override
		// a标签加属性target=_blank或者window.open打开新装口会调用此方法
		public boolean onCreateWindow(WebView view, boolean isDialog,
				boolean isUserGesture, Message resultMsg) {
			try {
				WebView newWebView = new WebView(view.getContext());
				newWebView.setWebViewClient(new WebViewClient() {
					@Override
					public boolean shouldOverrideUrlLoading(WebView view,
							String url) {
						commloadUrl(url);
						return true;
					}
				});
				WebViewTransport transport = (WebViewTransport) resultMsg.obj;
				transport.setWebView(newWebView);
				resultMsg.sendToTarget();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
			return true;
		}
	}

	class MyWebViewClient extends WebViewClient {
		/**
		 * 加载失败
		 */
		private boolean mIsLoadError = false;

		@Override
		public void onReceivedHttpAuthRequest(WebView view,
				HttpAuthHandler handler, String host, String realm) {
		}

		@Override
		public void onReceivedError(WebView view, int errorCode,
				String description, String failingUrl) {
			super.onReceivedError(view, errorCode, description, failingUrl);
			mIsLoadError = true;
		}

		@Override
		public boolean shouldOverrideUrlLoading(WebView view, String urlString) {
			BallLog.i(TAG, "shouldOverrideUrlLoading");
            view.loadUrl(urlString);
			//funSetCookie(urlString, mContext);
			return true;
		}

		@Override
		public void onReceivedSslError(WebView view, SslErrorHandler handler,
				SslError error) {
			// 接受所有网站的证书
			handler.proceed();
		}

		@Override
		public void onLoadResource(WebView view, String url) {
			//injectJavascriptInterfaces(view);
			super.onLoadResource(view, url);
			mIsLoadError = false;
		}

		@Override
		public void onPageStarted(WebView view, String url, Bitmap favicon) {
			//injectJavascriptInterfaces(view);
			super.onPageStarted(view, url, favicon);
			// DialogUtil.showLoadingDialog(mContext);
			//mIsLoadFinished = false;

		}

		@Override
		public void onPageFinished(WebView view, String url) {

			//injectJavascriptInterfaces(view);
			super.onPageFinished(view, url);
			//mIsLoadFinished = true;

			}
			//loadUrl(userInfoJs);
			//addJsUrl(mJsList);


		}


	}

//	public final class JavaScriptInterface {
//
//		JavaScriptInterface() {
//
//		}

		/**
		 * 网页拨打电话
		 * 
		 * @param number
		 *            电话号码
		 * @author wangshuaibo
		 */
		//@JavascriptInterface
//		public void nativeCallByNumber(final String number) {
//			post(new Runnable() {
//				public void run() {
//					BabytreeLog.d(TAG, "nativeCallByNumber number[" + number
//							+ "]");
//					try {
//						Intent intent = new Intent();
//						// 系统默认的action，用来打开默认的电话界面
//						intent.setAction(Intent.ACTION_DIAL);
//						intent.setData(Uri.parse("tel:" + number));
//						if (BabytreeUtil.hasIntentActivities(mContext, intent)) {
//							mContext.startActivity(intent);
//						} else {
//							Toast.makeText(mContext, "对不起，该设备不能拨打电话",
//									Toast.LENGTH_SHORT).show();
//						}
//					} catch (Throwable e) {
//						e.printStackTrace();
//					}
//				}
//			});
//		}


//}
